//
//  BMWShareView.swift
//  BMWShare
//
//  Created by 李胜兵 on 2019/6/3.
//  Copyright © 2019年 shanghai. All rights reserved.

import UIKit

/// Interface protocol
public protocol BMWShareViewInterfaceProtocol {
    
    var  sharePlatforms: [BMWPlatform] { get }
    var  shareContents: [BMWShareManager.ContentKey: Any]? { get }
    var  isHiddenIfNotInstallPlatform: Bool { get }
    func showShareView(_ mode: BMWShareView.ShareViewMode?)
    func dismissShareView()
    func getShareComplete(block: @escaping (_ platfomeName: BMWPlatform, _ indexPath: IndexPath, _ shareResult: String) -> Void)
    func cancelShareViewComplete(block: @escaping () -> Void)
    func beginShareViewComplete(block: @escaping (_ platfomeName: BMWPlatform, _ indexPath: IndexPath) -> Void)
    func endShareViewComplete(block: @escaping (_ platfomeName: BMWPlatform, _ indexPath: IndexPath, _ shareResult: String) -> Void)
}

/// UI protocol
public protocol BMWShareViewUIProtocol {
    
    /// proprety's
    var numberOfLines: Int { get set}
    var bmwShareViewAlpha: CGFloat {get set}
    var bmwShareViewBackgroundColor: UIColor {get set}
    var bmwContentViewHeight: CGFloat {get set}
    var bmwContentViewEdgeInsets: UIEdgeInsets {get set}
    var bmwContentViewRadius: CGFloat {get set}
    var bmwContentViewBackgroundColor: UIColor {get set}
    var bmwCollectionViewBackgroundColor: UIColor {get set}

    var bmwCancelButtonHeight: CGFloat {get set}
    var bmwCancelButtonTopMargin: CGFloat {get set}
    var bmwCancelButtonAttributes: [NSAttributedString.Key : Any] {get set}
    var bmwCancelButtonBackgroundColor: UIColor {get set}
    
    /// function's
    func setBMWShareViewAlpha(forAlpha: CGFloat)
    func setBMWShareViewBackgroundColor(forColor: UIColor)
    func setBMWContentViewHeight(forHeight: CGFloat)
    func setBMWContentViewEdgeInsets(forEdgeInsets: UIEdgeInsets)
    func setBMWContentViewRadius(forRadius: CGFloat)
    func setBMWContentViewBackgroundColor(forColor: UIColor)
    func setBMWCollectionViewBackgroundColor(forColor: UIColor)

    func setBMWCancelButtonHeight(forHeight: CGFloat)
    func setBMWCancelButtonTopMargin(forTopMargin: CGFloat)
    func setBMWCancelButtonAttributes(forAttributes: [NSAttributedString.Key : Any])
    func setBMWCancelButtonBackgroundColor(forBackgroundColor: UIColor)
}


open class BMWShareView: UIView, BMWShareViewUIProtocol, BMWShareViewInterfaceProtocol {
    
   public var numberOfLines: Int = 1
   public var bmwShareViewAlpha: CGFloat = 0.5
   public var bmwShareViewBackgroundColor: UIColor = UIColor.black
   public var bmwContentViewHeight: CGFloat = NumberOfLinesType.one.value
   public var bmwContentViewEdgeInsets: UIEdgeInsets = UIEdgeInsets(top: 0, left: 8, bottom: 48, right: 8)
   public var bmwContentViewRadius: CGFloat = 14
   public var bmwContentViewBackgroundColor: UIColor = UIColor.clear
   public var bmwCollectionViewBackgroundColor: UIColor = UIColor.hexStringToColor(hexString: "#F8F8F8").withAlphaComponent(0.82)
   public var bmwCancelButtonHeight: CGFloat = 56
   public var bmwCancelButtonTopMargin: CGFloat = 8
   public var bmwCancelButtonBackgroundColor: UIColor = UIColor.white
   public var bmwCancelButtonAttributes: [NSAttributedString.Key : Any] = [NSAttributedString.Key.foregroundColor: UIColor.hexStringToColor(hexString: "#007AFF"), NSAttributedString.Key.font: UIFont.systemFont(ofSize: 20)]
    
    
   public var isHiddenIfNotInstallPlatform: Bool = false
   public var sharePlatforms: [BMWPlatform] = [BMWPlatform.weixin, BMWPlatform.pengyouquan, BMWPlatform.qq, BMWPlatform.weibo]
   public var shareContents: [BMWShareManager.ContentKey: Any]? {
        didSet {
            BMWContentCollectionView.userInfo = self.shareContents
        }
    }
    
    /// Content View will add UI.
    public lazy var contentView: UIView = UIView()
    /// Cancel button.
    fileprivate lazy var cancelButton: UIButton = UIButton()
    /// CollectionView
    fileprivate lazy var collectionView: BMWShareCollectionView = BMWShareCollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout())
    
    /// Given's view from outside, will container all view's.
    fileprivate var containerView: UIView!
    /// Class's property for record previous containerView, When the second shareView is freely displayed, loop the previous container view, delete the last shareview that did not disappear.
    fileprivate static var previousContainerView: UIView = UIView()
    fileprivate var mode: BMWShareView.ShareViewMode = .view
    fileprivate lazy var viewModel: BMWShareViewModel = BMWShareViewModel()
    fileprivate var shareComplete: ShareComplete?
    fileprivate var endShareViewComplete: ShareComplete?
    typealias CancelShareViewCallBack = () -> Void
    fileprivate var cancelShareViewCallBack: CancelShareViewCallBack?
    typealias BeginShareViewComplete = (_ title: BMWPlatform, _ indexPath: IndexPath) -> Void
    fileprivate var beginShareViewComplete: BeginShareViewComplete?
    
    public init(containerView: UIView) {
        super.init(frame: CGRect.zero)
        self.containerView = containerView
        setupUI()
    }
    
    fileprivate func setupUI() {
        addSubview(contentView)
        contentView.addSubview(collectionView)
        contentView.addSubview(cancelButton)
        cancelButton.addTarget(self, action: #selector(cancelBtn), for: .touchUpInside)
        
        NotificationCenter.default.addObserver(self, selector: #selector(receiveNotification(noti:)), name: Notification.Name.init("WillDismissShareView"), object: nil)
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }
    
    required public init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        dismissShareView()
    }
    
    override open func layoutSubviews() {
        super.layoutSubviews()
        if self.sharePlatforms.count <= 4 {
            self.numberOfLines = 1
        }
        BMWShareViewModel.rows = self.numberOfLines
        bmwContentViewHeight = numberOfLines == 1 ? NumberOfLinesType.one.value : NumberOfLinesType.two.value
        collectionView.dataSourceForArray = viewModel.dataSourceWithFilterAfter(bmwSharePlatforms: self.sharePlatforms, isHiddenIfNotInstallPlatform: self.isHiddenIfNotInstallPlatform)
        self.frame = mode == .window ? (UIApplication.shared.keyWindow?.bounds ?? CGRect.zero) : containerView.bounds
        self.contentView.frame = CGRect(x: bmwContentViewEdgeInsets.left, y: self.bounds.height - (bmwContentViewEdgeInsets.bottom + bmwContentViewHeight), width: self.bounds.width - bmwContentViewEdgeInsets.left - bmwContentViewEdgeInsets.right, height: bmwContentViewHeight)
        
        self.collectionView.frame = CGRect(x: 0, y: 0, width: self.contentView.bounds.width, height: self.contentView.bounds.height - bmwCancelButtonHeight - bmwCancelButtonTopMargin)
        self.cancelButton.frame = CGRect(x: 0, y: collectionView.frame.maxY + bmwCancelButtonTopMargin, width: collectionView.bounds.width, height: bmwCancelButtonHeight)
        
        self.drawUI()
    }
    
    fileprivate func drawUI() {
        //self.alpha = bmwShareViewAlpha, if this setup, will cause all UI is becoming transparent. please use the following settings.
        self.backgroundColor = bmwShareViewBackgroundColor.withAlphaComponent(bmwShareViewAlpha)
        
        contentView.layer.cornerRadius = bmwContentViewRadius
        contentView.layer.masksToBounds = true
        contentView.backgroundColor = bmwContentViewBackgroundColor
        
        cancelButton.backgroundColor = bmwCancelButtonBackgroundColor
    
        cancelButton.setTitle(
            BMWNSLocalizedString.localizedString("BMWSHAREUI_CANCEL_BUTTON_TITLE", comment: "cancel button"),
            for: .normal)
        cancelButton.titleLabel?.font = bmwCancelButtonAttributes[NSAttributedString.Key.font] as? UIFont
        cancelButton.setTitleColor(bmwCancelButtonAttributes[NSAttributedString.Key.foregroundColor] as? UIColor, for: .normal)
        cancelButton.setTitleColor((bmwCancelButtonAttributes[NSAttributedString.Key.foregroundColor] as? UIColor)?.withAlphaComponent(0.25), for: .highlighted)
        cancelButton.layer.cornerRadius = bmwContentViewRadius
        
        collectionView.layer.cornerRadius = bmwContentViewRadius
        collectionView.backgroundColor = bmwCollectionViewBackgroundColor
    }
    
    
    
    /// Show shareView, mode default is view
    ///
    /// - Parameter mode: default is view
    open func showShareView(_ mode: BMWShareView.ShareViewMode? = .view) {
        self.alpha = 1.0
        BMWShareView.previousContainerView.subviews.forEach({
            if $0 is BMWShareView {
                $0.removeFromSuperview()
            }
        })
        
        let tempMode = mode == nil ? .view : mode!
        switch tempMode {
        case .view:
            containerView.addSubview(self)
            BMWShareView.previousContainerView = containerView
        case .window:
            guard let window = UIApplication.shared.keyWindow else { return }
            window.addSubview(self)
            BMWShareView.previousContainerView = window
        }
        UIView.animate(withDuration: 0.5, delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 5.0, options: [], animations: {
            var newFrame = self.contentView.frame
            newFrame.origin.y -= (self.bmwContentViewEdgeInsets.bottom + self.bmwContentViewHeight)
            self.contentView.frame = newFrame
        }) { (_) in }
    }
    
    /// dismiss shareView
    @objc open func dismissShareView() {
        
        UIView.animate(withDuration: 0.5, delay: 0.0, usingSpringWithDamping: 0.9, initialSpringVelocity: 5.0, options: [], animations: {
            var newFrame = self.contentView.frame
            newFrame.origin.y += (self.bmwContentViewEdgeInsets.bottom + self.bmwContentViewHeight)
            self.contentView.frame = newFrame
            self.alpha = 0.0
        }) { (_) in
            self.removeFromSuperview()
        }
    }
    
    @objc func cancelBtn() {
        self.dismissShareView()
        if cancelShareViewCallBack != nil {
           cancelShareViewCallBack!()
        }
    }
    
    /// ShareComplete: Call Back
    ///
    /// - Parameter block: (_ title: String, _ indexPath: String, _ shareResult: String) -> Void
    public func getShareComplete(block: @escaping ShareComplete) {
        self.shareComplete = block
    }
    
    /// End shareView callback'
    public func endShareViewComplete(block: @escaping ShareComplete) {
        self.endShareViewComplete = block
    }
    
    // callback: cancelShareView
    public func cancelShareViewComplete(block: @escaping () -> Void) {
        self.cancelShareViewCallBack = block
    }
    
    // Begin shareView callback'
    public func beginShareViewComplete(block: @escaping (BMWPlatform, IndexPath) -> Void) {
        self.beginShareViewComplete = block
    }
}


// MARK: - Notification'
extension BMWShareView {
    public typealias PlatformIndexPath = IndexPath
    public typealias ShareResult = String
    public typealias ShareComplete = (_ title: BMWPlatform, _ indexPath: PlatformIndexPath, _ shareResult: ShareResult) -> Void
    @objc func receiveNotification(noti: Notification) {
        self.dismissShareView()
        guard let info = noti.userInfo as? [String: Any] else {
            return
        }
        let title = info["title"] as? BMWPlatform ?? .weixin
        let indexPath = info["indexPath"] as? IndexPath ?? IndexPath(row: 0, section: 0)
        
        /// begin shareView callback'
        if self.beginShareViewComplete != nil {
           self.beginShareViewComplete!(title, indexPath)
        }
        
        /// end shareView callback'
        BMWShareManager.shareComplete = { result in
            if self.shareComplete != nil {
                self.shareComplete!(title, indexPath, result)
            }
            
            if self.endShareViewComplete != nil {
                self.endShareViewComplete!(title, indexPath, result)
            }
        }
    }
}


extension BMWShareView {
    
   public func setBMWContentViewHeight(forHeight: CGFloat) {
        bmwContentViewHeight = forHeight
    }
    
   public func setBMWShareViewAlpha(forAlpha: CGFloat) {
        bmwShareViewAlpha = forAlpha
    }
    
   public func setBMWShareViewBackgroundColor(forColor: UIColor) {
        self.backgroundColor = forColor.withAlphaComponent(bmwShareViewAlpha)
    }
    
   public func setBMWContentViewEdgeInsets(forEdgeInsets: UIEdgeInsets) {
        bmwContentViewEdgeInsets = forEdgeInsets
    }
    
   public func setBMWContentViewRadius(forRadius: CGFloat) {
        bmwContentViewRadius = forRadius
    }
    
   public func setBMWContentViewBackgroundColor(forColor: UIColor) {
        self.contentView.backgroundColor = forColor
    }
    
   public func setBMWCollectionViewBackgroundColor(forColor: UIColor) {
        bmwCollectionViewBackgroundColor = forColor
    }
    
   public func setBMWCancelButtonHeight(forHeight: CGFloat) {
        bmwCancelButtonHeight = forHeight
    }
    
   public func setBMWCancelButtonTopMargin(forTopMargin: CGFloat) {
        bmwCancelButtonTopMargin = forTopMargin
    }
    
   public func setBMWCancelButtonAttributes(forAttributes: [NSAttributedString.Key : Any]) {
        bmwCancelButtonAttributes = forAttributes
    }
    
   public func setBMWCancelButtonBackgroundColor(forBackgroundColor: UIColor) {
        bmwCancelButtonBackgroundColor = forBackgroundColor
    }
}

extension BMWShareView {
    public enum ShareViewMode {
        case view
        case window
    }
}

extension BMWShareView {
    enum  NumberOfLinesType {
        case one
        case two
        
        var value: CGFloat {
            switch self {
            case .one:
                return 193
            case .two:
                return 129 * 2 + 30
            }
        }
    }
}
